iT邦幫忙

DAY 21
0

以Asp .Net MVC 5 為基礎,建立自己的程式開發框架系列 第 21

搜索頁面 - ViewModel的定義

  • 分享至 

  • xImage
  •  

在上一篇介紹完了搜索功能的概念和思路之後,在這一篇開始要看實作的部份。

通常寫Mvc都是從Model開始,因此這一篇將來看一下搜索功能所會使用到的ViewModel

同步發表於我的部落格:http://alantsai2007.blogspot.com/2014/10/BuildYourOwnApplicationFrameworkOnMvc-21-IndexPage-ViewModel.html

ViewModel的內容

首先,搜索的ViewModel必然會有兩個Property:

  1. 搜索條件
  2. 搜索結果

因此,我們會先從這兩個部份的Property來看起。

搜索條件的ViewModel

搜索條件會有一定有的欄位和各個domain所需要的欄位,因此會先定義一個Base,好方便之後domain來繼承並且提供其他相關欄位。

一定會有的欄位像是:

  1. 每頁筆數
  2. 目前頁數
  3. 排序欄位
  4. 排序順序

Domain相關的欄位就依照各自的需求,例如假設是一篇文章,可能會有以「標題」做搜索或者以「內文」做搜索。

因此,程式碼會如下:

/// <summary>
/// 搜索 Form 的 ViewModel base。定義搜索必須要有的相關欄位。
/// </summary>
public abstract class SearchFormViewModelBase : ISearchFormViewModelBase
{
    /// <summary>
    /// 目前頁數的值
    /// </summary>
    private int page;

    /// <summary>
    ///  取得或設定目前頁數。最小值是1。
    /// </summary>
    /// <value>
    /// 目前頁數
    /// </value>
    public virtual int Page
    {
        get
        {
            if (this.page < 1)
            {
                this.page = 1;
            }

            return this.page;
        }

        set { this.page = value; }
    }

    /// <summary>
    /// 每頁筆數的值
    /// </summary>
    private int pageSize;

    /// <summary>
    /// 取得或設定每頁筆數。最小值是15。
    /// </summary>
    /// <value>
    /// 每頁筆數
    /// </value>
    public virtual int PageSize
    {
        get
        {
            if (this.pageSize < 1)
            {
                this.pageSize = 15;
            }

            return this.pageSize;
        }

        set { this.pageSize = value; }
    }

    /// <summary>
    /// 欄位排序的值
    /// </summary>
    protected string orderByColumnName;

    /// <summary>
    /// 取得或設定要依照那個欄位做排序。
    /// </summary>
    /// <value>
    /// 依照那個欄位做排序.
    /// </value>
    public abstract string OrderByColumnName { get; set; }

    /// <summary>
    /// 取得或設定排序的方向。
    /// </summary>
    /// <value>
    /// <c>true</c> 表示用 ascending排序; otherwise, <c>false</c>.
    /// </value>
    public bool IsAscending { get; set; }
}

這個ViewModel實作的Interface就不看了,基本上就是這些Property的定義。

這邊有個地方可以注意到就是排序的欄位。因為我們這個SearchFormViewModelBase沒有形態的概念,而通常來說搜索條件會和某一個DB的Table對應。因此,為了方便之後框架幫忙做搜索,這邊又定義一個有強型別的SearchFormViewModelBase:

/// <summary>
/// 搜索 Form 的 ViewModel base。有帶上形態,以第一個欄位做排序
/// </summary>
/// <typeparam name="T">Entity Framework裡面Table Entity</typeparam>
public abstract class SearchFormViewModelBase<T> : SearchFormViewModelBase
{
    /// <summary>
    /// 取得或設定要依照那個欄位做排序。
    /// </summary>
    /// <value>
    /// 依照那個欄位做排序.
    /// </value>
    public override string OrderByColumnName
    {
        get
        {
            if (string.IsNullOrEmpty(this.orderByColumnName))
            {
                this.orderByColumnName = typeof(T).GetProperties().First().Name;
            }

            return this.orderByColumnName;
        }

        set
        {
            this.orderByColumnName = value;
        }
    }
}

可以注意到這個Class的定義是Abstract,表示之後的class應該要依照自己的Domain去做繼承,例如如果今天是Post的搜索ViewModel,希望有一個 「標題」的搜索欄位,和排序要以「建立時間」欄位,那麼ViewModel就會是:

public class SearchFormViewModel : SearchFormViewModelBase<Post>
{
    [DisplayName("標題")]
    public string Title { get; set; }

    public override string OrderByColumnName
    {
        get
        {
            return "CreateDateTime";
        }
    }
}

搜索結果

這個部份就比較簡單,就是某一個和Detail頁面一樣ViewModel不過是被一個IPagedList包住。因此他不會像搜索ViewModel一樣有個base而是直接看定義的 ViewModel然後以泛型的方式傳入。

PagedList.Mvc - 好用的分頁套件

搜索ViewModel的主檔

有了這兩個Property的ViewModel之後,就可以建立搜索的ViewModel的Base:

/// <summary>
/// 搜索頁面的ViewModel需要繼承這一個Base。
/// 方便處理Paging和搜索條件相關。
/// 這個方法就兩個Property,用作於表示搜索的form和搜索結果的result。
/// </summary>
/// <typeparam name="TSearchForm">搜索的form ViewModel type。
/// 必須是繼承<see cref="MvcInfrastructure.Common.Base.SearchFormViewModelBase"/>
/// </typeparam>
/// <typeparam name="TPageResult">搜索的結果ViewModel type</typeparam>
public class SearchViewModelBase<TSearchForm, TPageResult> : 
	ISearchViewModelBase<TSearchForm, TPageResult>
    where TSearchForm : Core.Common.Base.ISearchFormViewModelBase, new() 
{
    private TSearchForm searchForm;

    /// <summary>
    /// 取得或設定搜索的Form。如果是null,會實例一個。
    /// </summary>
    /// <value>
    /// 搜索的Form
    /// </value>
    public TSearchForm SearchForm
    {
        get
        {
            if (this.searchForm == null)
            {
                this.searchForm = new TSearchForm();
            }

            return this.searchForm;
        }

        set { this.searchForm = value; }
    }

    /// <summary>
    /// 取得或設定搜索結果的ViewModel。
    /// </summary>
    /// <value>
    /// 搜索結果的ViewModel。用<see cref="PagedList.IPagedList"/>包住,方便做分頁
    /// </value>
    public IPagedList<TPageResult> Result { get; set; }
}

Post的搜索ViewModel

定義好了搜索的BaseViewModel之後,假設今天是Post頁面要做搜索的ViewModel,就可能會像是:

public class Index : SearchViewModelBase<SearchFormViewModel, SearchResult>
{
}

public class SearchResult : IMapFrom<Post>
{
    public int Id { get; set; }
    [DisplayName("標題")]
    public string Title { get; set; }
    [DisplayName("內文")]
    public string PostContent { get; set; }

}

public class SearchFormViewModel : SearchFormViewModelBase<Post>
{
    [DisplayName("標題")]
    public string Title { get; set; }

    public override string OrderByColumnName
    {
        get
        {
            return "CreateDateTime";
        }
    }
}

結語

有了搜索的ViewModel之後,在下一篇將會介紹框架的Service怎麼能夠做修改並且讓搜索處理邏輯變的簡單。


上一篇
搜索頁面 - 思考篇
下一篇
搜索頁面 - Service層的工作 -動態產生Linq條件
系列文
以Asp .Net MVC 5 為基礎,建立自己的程式開發框架30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言